/**
 * Copyright (c) 2011-2017, James Zhan 詹波 (jfinal@126.com).
 * <p>
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 * <p>
 * http://www.apache.org/licenses/LICENSE-2.0
 * <p>
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.jfinal.ext.kit;

import com.jfinal.kit.StrKit;
import org.apache.commons.lang.math.NumberUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * DateKit.
 *
 * @author CHEN
 */
public class DateKit {

	public static final String PATTERN_DATE = "yyyy-MM-dd";
	public static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
	public static final String PATTERN_DATEHOUR = "yyyy-MM-dd HH:00:00";
	public static final String PATTERN_yyyyMMddHHmmss = "yyyyMMddHHmmss";
	public static final String PATTERN_HOUR = "HH:00";

	public static Date toDate(String dateStr) {
		if (StrKit.isBlank(dateStr)) {
			return null;
		}

		dateStr = dateStr.trim();
		int length = dateStr.length();
		if (NumberUtils.isNumber(dateStr)) {
			//毫秒
			if (length == 13) {
				return new Date(Long.valueOf(dateStr));
			}
			//秒
			if (length == 10) {
				return new Date(Long.valueOf(dateStr) * 1000);
			}
		}

		SimpleDateFormat sdf;
		if (length == PATTERN_DATETIME.length()) {
			sdf = new SimpleDateFormat(PATTERN_DATETIME);
		} else if (length == PATTERN_DATE.length()) {
			sdf = new SimpleDateFormat(PATTERN_DATE);
		} else if (length == PATTERN_yyyyMMddHHmmss.length()) {
			sdf = new SimpleDateFormat(PATTERN_yyyyMMddHHmmss);
		}else {
			throw new IllegalArgumentException("The date format is not supported for the time being");
		}
		try {
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			dateStr = dateStr.replace(".", "-");
			dateStr = dateStr.replace("/", "-");
			try {
				return sdf.parse(dateStr);
			} catch (ParseException ex) {
				throw new IllegalArgumentException("The date format is not supported for the time being");
			}
		}

	}

	public static Date toDateByPattern(String dateStr, String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		try {
			return sdf.parse(dateStr);
		} catch (ParseException e) {
			e.printStackTrace();
		}
		return null;
	}

	public static Date toDate(String dateStr, String pattern) {
		return toDate(toDate(dateStr), pattern);
	}

	public static Date toDate(Date date, String pattern) {
		return toDate(toStr(date, pattern));
	}

	public static String toStr(Date date) {
		return toStr(date, DateKit.PATTERN_DATE);
	}


	public static String toStr(Date date, String pattern) {
		SimpleDateFormat sdf = new SimpleDateFormat(pattern);
		return sdf.format(date);
	}

	public static String toStr(String date, String pattern) {
		return toStr(toDate(date,pattern),pattern);
	}


	/**
	 * 获取当天凌晨0点0分0秒时间
	 */
	public static Date getStartOfDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	/**
	 * 获取当天晚上23点59分59秒时间
	 */
	public static Date getEndOfDay(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.HOUR_OF_DAY, 23);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}

	public static Date getStartOfHour(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}


	public static Date getEndOfHour(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.MINUTE, 59);
		calendar.set(Calendar.SECOND, 59);
		calendar.set(Calendar.MILLISECOND, 999);
		return calendar.getTime();
	}

	public static Date getStartOfMonth(Date date) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.set(Calendar.DAY_OF_MONTH, 1);
		calendar.set(Calendar.HOUR_OF_DAY, 0);
		calendar.set(Calendar.MINUTE, 0);
		calendar.set(Calendar.SECOND, 0);
		calendar.set(Calendar.MILLISECOND, 0);
		return calendar.getTime();
	}

	public static Date getEndOfMonth(Date date) {
		Calendar ca = Calendar.getInstance();
		ca.setTime(date);
		ca.set(Calendar.DAY_OF_MONTH, ca.getActualMaximum(Calendar.DAY_OF_MONTH));
		return DateKit.getEndOfDay(ca.getTime());
	}

	/**
	 * 获取特定的时间
	 *
	 * @param date
	 * @param amount 正数,获取n天后的时间; 负数,获取n天前的时间
	 * @return
	 */
	public static Date addDay(Date date, int amount) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		calendar.add(Calendar.DATE, amount);
		return calendar.getTime();
	}

	/**
	 * 获取选定日期的年List
	 */
	public static List<String> getYearList(Date startTime,Date endTime) {
		try {
			Calendar bef = Calendar.getInstance();
			Calendar aft = Calendar.getInstance();
			bef.setTime(startTime);
			aft.setTime(endTime);
			int startYear = bef.get(Calendar.YEAR);
			int endYear = aft.get(Calendar.YEAR);
			int n = endYear - startYear;

			List<String> list = new ArrayList<>();
			for (int i = 0; i <= n; i++) {
				list.add(String.valueOf(startYear + i));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取一年12个月的List
	 */
	public static List<String> getMonthList() {
		try {
			List<String> list = new ArrayList<>();
			for (int i = 0; i < 12; i++) {
				list.add(String.valueOf(i+1));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取选定日期的周List
	 */
	public static List<String> getWeekList(Date startTime,Date endTime) {
		try {
			Calendar bef = Calendar.getInstance();
			Calendar aft = Calendar.getInstance();
			bef.setFirstDayOfWeek(Calendar.MONDAY);
			aft.setFirstDayOfWeek(Calendar.MONDAY);
			bef.setTime(startTime);
			aft.setTime(endTime);
			int startWeek = bef.get(Calendar.WEEK_OF_YEAR);
			int endWeek = aft.get(Calendar.WEEK_OF_YEAR);
			int n = endWeek - startWeek;

			List<String> list = new ArrayList<>();
			for (int i = 0; i <= n; i++) {
				list.add(String.valueOf(startWeek + i));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取选定日期范围内的日期List
	 */
	public static List<String> getDayList(Date startTime,Date endTime) {
		try {
			int n = DateKit.differentDays(startTime,endTime,DateKit.PATTERN_DATE);
			if(n < 1) {
				return null;
			}
			Calendar calc = Calendar.getInstance();
			List<String> list = new ArrayList<>();
			for (int i = 0; i <= n; i++) {
				calc.setTime(startTime);
				calc.add(Calendar.DATE, i);
				Date minDate = calc.getTime();
				list.add(DateKit.toStr(minDate, DateKit.PATTERN_DATE));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取选定日期每小时集合Map
	 */
	public static List<String> getHourList(Date date) {
		try {
			Calendar calc = Calendar.getInstance();
			List<String> list = new ArrayList<>();
			Date start = DateKit.getStartOfDay(date);
			for (int i = 0; i < 24; i++) {
				calc.setTime(start);
				calc.add(Calendar.HOUR_OF_DAY, i);
				Date minDate = calc.getTime();
				list.add(DateKit.toStr(minDate, DateKit.PATTERN_DATEHOUR));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取选定日期范围内每小时集合
	 */
	public static List<Date> getHourListFromDay(Date startTime,Date endTime) {
		try {
			int n = DateKit.differentHours(startTime,endTime,DateKit.PATTERN_DATEHOUR);
			List<Date> list = new ArrayList<>();
			if(n < 1) {
				list.add(DateKit.toDate(startTime,DateKit.PATTERN_DATEHOUR));
				return list;
			}
			Calendar calc = Calendar.getInstance();
			for (int i = 0; i <= n; i++) {
				calc.setTime(startTime);
				calc.add(Calendar.HOUR_OF_DAY, i);
				Date minDate = calc.getTime();
				list.add(DateKit.toDate(minDate, DateKit.PATTERN_DATEHOUR));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取一天每小时集合Map(00:00 ~ 24:00)
	 */
	public static List<String> getHourOfDayList() {
		try {
			Calendar calc = Calendar.getInstance();
			List<String> list = new ArrayList<>();
			Date start = DateKit.getStartOfDay(new Date());
			for (int i = 0; i < 24; i++) {
				calc.setTime(start);
				calc.add(Calendar.HOUR_OF_DAY, i);
				Date minDate = calc.getTime();
				list.add(DateKit.toStr(minDate, DateKit.PATTERN_HOUR));
			}
			return list;
		} catch (Exception e) {
			e.printStackTrace();
		}
		return null;
	}

	/**
	 * 获取两个日期间相差的天数的绝对值
	 * @param d1
	 * @param d2
	 * @param pattern
	 * @return
	 */
	public static int differentDays(Date d1, Date d2, String pattern) {
		try {
			d1 = DateKit.toDate(d1,pattern);
			d2 = DateKit.toDate(d2,pattern);
			return Math.abs((int) ((d1.getTime() - d2.getTime()) / (1000*3600*24)));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

	/**
	 * 获取两个日期间相差的小时数的绝对值
	 * @param d1
	 * @param d2
	 * @param pattern
	 * @return
	 */
	public static int differentHours(Date d1, Date d2, String pattern) {
		try {
			d1 = DateKit.toDate(d1,pattern);
			d2 = DateKit.toDate(d2,pattern);
			return Math.abs((int) ((d1.getTime() - d2.getTime()) / (1000*3600) ));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}

	/**
	 * 获取两个日期间相差的秒数的绝对值
	 * @param d1
	 * @param d2
	 * @param pattern
	 * @return
	 */
	public static int differentSeconds(Date d1, Date d2, String pattern) {
		try {
			d1 = DateKit.toDate(d1,pattern);
			d2 = DateKit.toDate(d2,pattern);
			return Math.abs((int) ((d1.getTime() - d2.getTime()) / 1000 ));
		} catch (Exception e) {
			e.printStackTrace();
		}
		return -1;
	}


	public static void main(String[] args) {
//        List<String> list = getDayList(DateKit.toDate("2018-09-10",DateKit.PATTERN_DATE),DateKit.toDate("2018-09-17",DateKit.PATTERN_DATE));
//        Date date = DateKit.getEndOfDay(new Date());
		List<Date> list = DateKit.getHourListFromDay(DateKit.toDate("2018-09-18 10:00:59"),DateKit.toDate("2018-09-18 11:10:00"));
		System.out.println(list);
	}


}






